home *** CD-ROM | disk | FTP | other *** search
/ MacFormat España 22 / macformat_22.iso / Shareware / Programación / enteract-377 / enteract-377.sit / EnterAct Stuff / code to call Drag_ons / Call_Resource.c
Encoding:
C/C++ Source or Header  |  1996-05-24  |  37.3 KB  |  2 lines  |  [TEXT/KEEN]

  1. Call_Resource.cTEXTKEENëò≠Àæv≠ÀævÅÅä˙/* Call_Resource.c: file to be added to any applications wishing tocall the code resources that come with EnterAct.Note the other Call_Resource.c file on your source disk is adapted for usewith Minimal App. *//* Copyright © 1991 the Free Software Foundation, Inc. *         This file is free software; you can redistribute or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 1, or any later version. *         This file is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. *         You should have received a copy of the GNU General Public License * along with GAWK; see the file "COPYING hAWK". If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * Written for THINK C 4 on the Macintosh by Ken Earle (Dynabyte) Aug 1991. *//*REVISION May 96: who needs version flags in a prototype? There is just oneformat now for the CallResource() call. If you have been using CallResource()in your app, note the new prototype isvoid CallResource    (short        menuID,    short        item,    Boolean        concurrent,        // set FALSE if you don't support concurrent mode    char        *commandLineP    // -> complete command line or NULL    );Now your CallResource() will have the same arguments no matter which versionyou support. If you don't support concurrent operation (see below) then justset "concurrent" to FALSE. If you aren't passing in a command line, setcommandLineP to NULL. If you want to support concurrent operation, you willstill need to set VERSION2 TRUE as explained below. To pass a command line,put a pointer to a C string in commandLineP in the CallResource() call inyour application (no changes needed here).To call EnterAct-style code resources from your application:1    Add a copy of this file to your app.2    Call "InitCallResources()" in your startup code, just before    entering your event loop. The arguments are:    vRefNumForApp : preferably your application working directory, or 0    codeFolderName : preferably (Ptr)"\pDrag_on Modules"    menuID : the integer menu id of the menu you wish code resources        to be appended to. Preferably not File or Edit.3    Call "CallResource()" to handle the code resources picked from    the menu you have added them to. Typically looks something like        #define    MenuInQuestion    261        void DoMenuInQuestionCommand(short item)            {            switch (item)                {            case 1:                DoItemOne();            break;            case 2:                DoItemTwo();            break;            ...etc...            default:                if (item > 0)                    CallResource(MenuInQuestion, item, T/F, cmdLineP/NULL);            break;                }            }4    Go through the extension ("callback") functions defined at the    bottom of this file, and decide which ones you wish to support.    You will probably not be able to support "InDictionary()", and    "GetNextMultiFile()" requires that your application keep a list    of files for some purpose or other (typically searching), but if    your application supports text files you should be able to provide    support for the others. Note "GetScreenHeight" and "GetScreenWidth"    are done here, no modification needed. The code resources supplied    with EnterAct can still do useful things even if no extensions are    supplied.        If you decide not to support a particular extension, you need only    set the corresponding pointer to NULL in the function SetUpCodeCommunication().    For example, if you don't support InDictionary_Ext, then put        gacc.InDictionary_Ext = NULL;    in SetUpCodeCommunication().        For more about the "DoEventLoopOnce()" callback, see 6 below.    5    "ShowResult" and "SelectResult" defined below are called by    "CallResource" in response to a request by a code resource to display    the text results of the code resource run. If your application supports    TEXT documents, you should modify these functions to provide your    equivalents for these abilities. Otherwise, leave them as-is.6    Version 2 of hAWK (the one you received with this file) supports    concurrent execution. This means you fire up a hAWK program, go back    to working in your application (or even switch to some other app)    and hAWK notifies you when the program is done. There is a    penalty in speed of the hAWK program, usually far outweighed by    the benefit of being able to go back to work instantly rather than    having to sit there watching the watch cursor. Your calling application    should not be noticeably affected, except when the hAWK program    is doing something massive such as a huge "sort" or a large "copy".The "VERSION2" defined constant just below should be set to TRUE ifyou wish to support concurrent execution of hAWK programs, FALSEif you do not. That's all that VERSION2 affects. Read Resource cannotrun concurrently, and is not affected by the value of VERSION2.To support concurrent exec of hAWK programs, follow these steps:    1    define VERSION2 just below to be TRUE    2    In the menu where you call Drag_on Modules, use        ...CallResource(MenuInQuestion, item, bool);        rather than just CallResource(MenuInQuestion, item);        -the "bool" variable is a Boolean, to be set to TRUE if        you want concurrent execution. Recommended interface is        to set this variable FALSE if the user has held down        either the <Shift> or <Option> key or both, and set it        TRUE otherwise.    3    One additional callback function needs to be provided,        in "DoEventLoopOnce()" below. Your callback should        have the form            extern void HandleOneEvent(void);        and can be a copy of your main event loop function,        except that it should handle just one event and then        return, and startup initializations if any can        be skipped (creating a region to track the mouse,        for example). If you use a global event record, you        can use the same global in your "HandleOneEvent"        function, but keep in mind that when "CallResource()"        returns, your global event record will reflect the        last event processed during your Drag_on Module run,        rather than the original menu call -- check what your        main event loop does with the event after the orginal        call, and verify that nothing important will be confused        by having the nature of the event changed during the        Drag_on Modules run.        (Note your event handler does not need to do any special        checking for the <Command><period> that stops hAWK.)    4    If your calling app is in the background when hAWK        finishes a run, a notice will be installed by the        DoNotify() routine below, flashing an icon in the        menu bar etc until you return to the calling app.        In your MAIN event handler (not the handle-one-event)        you should place the following bit of code to properly        handle the notify when your app resumes:            --declaration at the top of its file;                -- to handle concurrent Drag_on Modules --                Boolean gNotifying;                Boolean gHawkIsRunning;                NMRec    gNotifyRec;                        -- and in your main event handler, for the case of            "kSuspendResumeMessage";                if (gNotifying)                    {                    NMRemove(&gNotifyRec);                    if (gNotifyRec.nmIcon)                        ReleaseResource(gNotifyRec.nmIcon);                    gNotifying = FALSE;                    ShowResultsAfterNotify();                    }        You will also need the standard global that records        whether or not your application is in the background,            Boolean gInBackground;        This variable should be set in your handle-one-event        function, and if your spelling of this variable name        differs from "gInBackground", change it here as well.        This file requires access to "gInBackground" in order        to determine if a notice should be posted at the end        of a hAWK program run.    5    In both your main event handler and the one-event        handler, calculate the "sleep" parameter for your        WaitNextEvent() call roughly as            gHawkIsRunning ? 2UL : GetCaretTime()        --adjust to suit your taste.    6    If you want the small icon "hAWK!" to flash for        notifications, move it to your application from "hAWK"        itself (it's just stored there).    7    One little wrinkle: what happens if you Quit your        application while hAWK is running? The recommended        solution here is to ask your user to issue a        <Command><period> to halt hAWK before proceeding        with the Quit. If you just pull the rug out from        under hAWK, files will probably be left open.        Sketchily:            Boolean DoQuit (...            extern Boolean gHawkIsRunning;...            if (gHawkIsRunning)                {                FlexAlert(justOK, stopIcon, "Please terminate your hAWK program \        with <Command><period> before quitting.");                return(FALSE);                }...*/#include <string.h>#ifndef NULL#define NULL        ((void *) 0)#endif/* Change this to TRUE if you support concurrent hAWK - see above, point 6. */#define VERSION2 FALSE#if VERSION2 == TRUEextern Boolean gInBackground;extern Boolean gNotifying;extern Boolean gHawkIsRunning;extern NMRec    gNotifyRec;#endif/* Canned options, if you want to get going in a hurry:SUPPORT_LEVEL should be set to one of the following four options:MINIMAL - no extensions, no showing of results after a code resource run.    Note this doesn't mean the code resource won't be creating a text file,    it just means your application won't be showing it.RESULTSONLY - no extensions, but ability to show results supplied by you.    This means you should provide the hooks in ShowResult() and    SelectResult() - nothing else to do.BASICTEXT - in addition to providing the hooks in ShowResult() and    SelectResult(), fill in the blanks in GetFrontText() to allow the    code resource access to your front text window during a run.CUSTOMSUPPORT - ie avoid the above canned options.There is one special case: if you support the "GetAppClip" extension,you’ll need to set SUPPORT_LEVEL to CUSTOMSUPPORT, and alsodefine VERSION2 TRUE (getclip was not supported by version 1). NOTE this willalso activate the PutAppClip extension. You must put your own function callsinto GetAppClip and PutAppClip to make them functional.*/#define MINIMAL            1#define RESULTSONLY        2#define BASICTEXT        3#define CUSTOMSUPPORT    4/* Pick yer pleasure - from the above 4 options only, please. */#define SUPPORT_LEVEL MINIMAL/* Struct passed to all code resources. Everything should be optional."stdInFileName" is primarily for code resources that insist on having inputfrom an existing file - hAWK, for example. "stdOutFileName", however, ishandy for use by any code resource that creates text, as this file can beshown by the calling application */typedef struct AppCodeComm    {    // c strings except as noted    char        *stdInFileName,    // text from application to code resource                *stdInFileNameP, // pascal version of above                *stdOutFileName, // text from code resource to application                *stdErrFileName, // error messages from code resource                *callerName,     // the name of your application                *thisCodeName;     // name of code resource being called    short            result;    short            version; // currently 1 or 2// Extension ("callback") functions - ALL OPTIONAL. These pointers-to-functions// are all set in  SetUpCodeCommunication() just before calling a code resource.    short            (*InDictionary_Ext)(char *tokenName);    Handle        (*GetFrontText_Ext)(Boolean getItAll);    void        (*GetNextMultiFile_Ext)(short *panePtr, short *indexPtr,                 short *vRefNumPtr, char *fileName, Boolean clearFlag);    short         (*OKStopAlert_Ext)(Ptr cstringPtr);    void        (*MemoryAlert_Ext)(void);    short            (*GetScreenHeight_Ext)(void);    short            (*GetScreenWidth_Ext)(void);    void        (*ShowWatchCursor_Ext)(void);// Concurrent exec, added for version 2    void        (*DoEventLoopOnce_Ext)(void);// Access to scrap/clip of calling app    Handle        (*GetAppClip_Ext)(void);// Added for version 3    long        extendID; // Caller should set to 'VER3'    short        (*PutAppClip_Ext)(char *newClipStr);// End of callback functions.// Added for version 4    long        extend2ID; // Caller should set to 'VER4'    char        *commandLine;    } AppCodeComm, *ACCPtr;static AppCodeComm    gacc;/* Your application name goes here. */static char callerName[] = "MyApp";typedef void (*CallCode)(ACCPtr ac);static char *stdPathP;typedef struct SpecificFolder    {    char     volName[32];    long    theDirID;    short        vRefNum;    } SpecificFolder;static SpecificFolder codeFolder;/* Functions defined in this file: *//* Call this one towards the end of your startup, just before event loop */void InitCallResources(short vRefNumForApp, char *codeFolderName, short menuID);/* Called by InitCallResource: */void SetUpStandardFileNames(short vRefNum);void ShowResourcesInMenu(short vRefNumForApp,     char *codeFolderName, short menuID);/* Two support routines for above */long FindCodeResFolder(short vRefNumForApp, char *codeFolderName);void AddCodesToMenu(long theDirID, short menuID);void OpenWDForCODE(void);/* Call this one in the "default" part of the switch for themenu containing the code resource names */void CallResource    (short        menuID,    short        item,    Boolean        concurrent,        // set FALSE if you don't support concurrent mode    char        *commandLineP    // -> complete command line or NULL    );#if VERSION2 == TRUE/* Enable/disable Drag_ons if running concurrently */void XableDrag_ons(short menuID, Boolean enable);/* Post a notify - NOTE this must be cleared by calling app */void DoNotify(void);/* For delayed showing of results */void ShowResultsAfterNotify(void);/* Beep and flush events */void AnnounceCompletion(void);#endif/* Called by CallResource(), decide which extension functions to pass along */Boolean SetUpCodeCommunication(char *progName, char *commandLineP);/* Called by CallResource() to display results of resource run */Boolean ShowResult(char *name); /* either stdout or stderr */void SelectResult(void);/* A few support functions: *//* Pascal strings */void CopyPStr(Byte *srcStr, Byte *dstStr);void AppendPStr(Byte *s1, Byte *s2);Boolean PasEqualStrs(char *aStr, char *bStr);/* Files, names and locations */Byte *FullPathNameFromDirectory(long DirID, short vRefNum, Byte *s);Byte *FullPathNameFromVRefNum(short vRefNum, Byte *s);short    OpenWorkingDirectoryFromFullName(char *name, short len);/* The extension functions - wrappers for your own calls */short InDictionary(char *tokenName);Handle GetFrontText(Boolean getItAll);void GetNextMultiFile(short *panePtr, short *indexPtr,             short *vRefNumPtr, char *fileName, Boolean clearFlag);short OKStopAlert(Ptr cstringPtr);void MemoryAlert(void);short GetScreenHeight(void);short GetScreenWidth(void);void ShowWatchCursor(void);void DoEventLoopOnce(void);Handle GetAppClip(void);short PutAppClip(char *newClipStr);/* Call just before entering your event loop.Sets up full path names for standard in/out/err files,adds any code resources present to the menu of your choice.*/void InitCallResources(short vRefNumForApp, char *codeFolderName, short menuID)    {    SetUpStandardFileNames(vRefNumForApp);    ShowResourcesInMenu(vRefNumForApp, codeFolderName, menuID);    }/* Called once at beginning of application. Sets up full path namesfor std in/out/err files, and as a bonus sets gacc.callerName.The vRefNum passed in should be the application's vRefNum, butcan be any old thing you want.-you can determine your application vrefnum at startup withshort        appVRefNum;if (GetVol(NULL, &appVRefNum))    appVRefNum = 0; */void SetUpStandardFileNames(short vRefNum)    {    if (!vRefNum)        GetVol(NULL, &vRefNum);    stdPathP = NewPtr(256);    if (MemError() != noErr)        goto PathTrouble;    gacc.stdInFileName = NewPtr(256);    if (MemError() != noErr)        goto PathTrouble;    gacc.stdInFileNameP = NewPtr(256);    if (MemError() != noErr)        goto PathTrouble;    gacc.stdOutFileName = NewPtr(256);    if (MemError() != noErr)        goto PathTrouble;    gacc.stdErrFileName = NewPtr(256);    if (MemError() != noErr)        goto PathTrouble;    if (vRefNum)        (void)(FullPathNameFromVRefNum(vRefNum, (Byte *)stdPathP));    else        stdPathP[0] = 0;    PtoCstr(stdPathP);    strcpy((Ptr)(gacc.stdInFileName), (Ptr)stdPathP);    strcpy((Ptr)(gacc.stdInFileNameP), (Ptr)stdPathP);    strcpy((Ptr)(gacc.stdOutFileName), (Ptr)stdPathP);    strcpy((Ptr)(gacc.stdErrFileName), (Ptr)stdPathP);    strcat((Ptr)(gacc.stdInFileName), "$tempStdIn");    strcat((Ptr)(gacc.stdInFileNameP), "$tempStdIn");    strcat((Ptr)(gacc.stdOutFileName), "$tempStdOut");    strcat((Ptr)gacc.stdErrFileName, "$tempStdErr");    CtoPstr((Ptr)(gacc.stdInFileNameP));    gacc.callerName = NewPtr(strlen(callerName)+1);    if (MemError() != noErr)        goto PathTrouble;    strcpy(gacc.callerName, callerName);        return;PathTrouble:    OKStopAlert("Out of memory right at the start! \Blew the tubes trying to allocate standard file names.");    ExitToShell();    }/* Index through folders in application's folder, looking for"\pDrag_on Modules". If found, index through files in folder and addany resource files found. */void ShowResourcesInMenu(short vRefNumForApp,     char *codeFolderName, short menuID)    {    long    theDirID;        if (theDirID = FindCodeResFolder(vRefNumForApp, codeFolderName))        AddCodesToMenu(theDirID, menuID);    }long FindCodeResFolder(short vRefNumForApp, char *codeFolderName)    {    HFileInfo    myCPB;    WDPBRec        theParms;    char        fName[32];    long        theDirID;    short            index = 1, len;    OSErr        err;        /* First extract "\pVolName:", volRef, and dirID for application folder */    theParms.ioNamePtr = (StringPtr)(codeFolder.volName);    theParms.ioVRefNum = vRefNumForApp;    theParms.ioWDIndex = 0;    theParms.ioWDProcID = 0;    theParms.ioWDVRefNum = 0;    if (PBGetWDInfo(&theParms,false))        return(0L);    len = codeFolder.volName[0];    codeFolder.volName[len + 1] = ':';    codeFolder.volName[0] = len + 1;    codeFolder.vRefNum = theParms.ioWDVRefNum;    theDirID = theParms.ioWDDirID;        myCPB.ioNamePtr = (StringPtr)fName;    myCPB.ioVRefNum = vRefNumForApp;    do        {        myCPB.ioFDirIndex = index;        myCPB.ioDirID = theDirID;        if ((err = PBGetCatInfo(&myCPB, FALSE)) == noErr)            {            if (((myCPB.ioFlAttrib>>4) & 0x01) == 1) /* a folder */                {                if (PasEqualStrs(fName, codeFolderName))                    return(myCPB.ioDirID);                }            }        ++index;        } while (err == noErr);    return(0L);    }/* Search thru folder for code resources and add all codes to the menu. */void AddCodesToMenu(long theDirID, short menuID)    {    HFileParam     fp;    MenuHandle     theMenu;    char        fName[32];    short            index = 1;    OSErr        err;    Boolean        firstAdd = TRUE;        theMenu = GetMHandle(menuID);    codeFolder.theDirID = theDirID;    fp.ioNamePtr = (StringPtr)fName;;    fp.ioVRefNum = codeFolder.vRefNum;    fp.ioFVersNum = 0;    do        {        fp.ioFDirIndex = index;        fp.ioDirID = codeFolder.theDirID;        if ((err = PBHGetFInfoSync((HParmBlkPtr)&fp)) == noErr)            {            if (fp.ioFlFndrInfo.fdType == 'rsrc'                && fp.ioFlFndrInfo.fdCreator == 'RSED')                {                if (firstAdd)                    {                    AppendMenu(theMenu, "\p-");                    firstAdd = FALSE;                    }                AppendMenu(theMenu, (StringPtr)fName);                }            }        ++index;        } while (err == noErr);    /****** Open a working directory for the CODE folder: this is currently required    for hAWK, but will be eliminated for hAWK's next version. */    if (!firstAdd)        OpenWDForCODE();    }/****** Open a working directory for the CODE folder: this is currently requiredfor hAWK, but will be eliminated for hAWK's next version. */void OpenWDForCODE()    {    WDPBRec        theParms;        theParms.ioCompletion = NULL;    theParms.ioVRefNum = codeFolder.vRefNum;    theParms.ioNamePtr = NULL;    theParms.ioWDDirID = codeFolder.theDirID;    theParms.ioWDProcID = 'ERIK';    if (!PBOpenWD(&theParms, FALSE)) /* IM IV pg 158 */        codeFolder.vRefNum = theParms.ioVRefNum;    }/* The main event. Given a pick from your menu, load and callthe resource. Display results if asked to by the resource.*/void CallResource    (short        menuID,    short        item,    Boolean        concurrent,        // set FALSE if you don't support concurrent mode    char        *commandLineP    // -> complete command line or NULL    )    {    MenuHandle     theMenu;    Handle        rHdle;    CallCode    codeCaller;    char        codeNameString[64];    long        eof;    short        saveVol, refNum;        theMenu = GetMHandle(menuID);    GetItem(theMenu, item, (StringPtr)codeNameString);    if (31 < (unsigned char)(codeNameString[0]))        {        /* An odd error: if the code resource was added to the menu during        startup, how can it have a name that is longer than a file name?        The assumption here is that we are calling something that is not a        code resource - either the wrong menu or an inappropriate item.        Uncomment the following alert if you want to double-check this.                OKStopAlert("Code resource name is too long.");        */        return;        }    gacc.thisCodeName = NULL;    if (GetVol(NULL, &saveVol))        saveVol = 0;    SetVol(NULL, codeFolder.vRefNum);    /* See if there's enough memory to load the code resource    - the brute force approach, if anything more strict than necessary. */    if (HOpenRF(codeFolder.vRefNum, codeFolder.theDirID,                (StringPtr)codeNameString, fsRdPerm, &refNum))        {        if (saveVol)            SetVol(NULL, saveVol);        OKStopAlert("Couldn't open the code resource.");        return;        }    if (GetEOF(refNum, &eof))        {        FSClose(refNum);        if (saveVol)            SetVol(NULL, saveVol);        OKStopAlert("Code resource seems damaged or empty - giving up.");        return;        }    FSClose(refNum);    rHdle = NewHandle(eof + eof/10); /* a guess */    if (MemError() != noErr)        {        if (saveVol)            SetVol(NULL, saveVol);        OKStopAlert("Not enough memory to proceed, sorry.");        return;        }    DisposHandle(rHdle);    rHdle = NULL;    if ((refNum = HOpenResFile(codeFolder.vRefNum, codeFolder.theDirID,                (StringPtr)codeNameString, fsRdPerm)) != -1 && refNum                && ResError() == noErr)        {        /* load CODE 0, set up extensions etc, lock down and call        -after, show results */        rHdle = Get1Resource ('CODE', 0);        if (!rHdle)            {            /* In error thinking it was a code resource - this really isn't fair */            CloseResFile(refNum);            if (saveVol)                SetVol(NULL, saveVol);            OKStopAlert("CODE 0 from that resource file seems to be missing.");            return;            }#if VERSION2 == TRUE        gHawkIsRunning = TRUE;        XableDrag_ons(menuID, FALSE);        HiliteMenu(0);#endif        HLock(rHdle);        codeCaller = (CallCode)*rHdle;        SetUpCodeCommunication(codeNameString, commandLineP);#if VERSION2 == TRUE        if (!concurrent)            gacc.DoEventLoopOnce_Ext = NULL;#endif        codeCaller(&gacc);                    HUnlock(rHdle);        ReleaseResource(rHdle);        CloseResFile (refNum);#if VERSION2 == TRUE        XableDrag_ons(menuID, TRUE);#endif        }    else        OKStopAlert("Could not open the resource fork for that code resource.");    if (saveVol)        SetVol(NULL, saveVol);    /* Show any file requested */    /* results:    <= -3 : no action at present    -2 : show stderr    -1 : user cancelled or error during dialog - no run    0  : run OK, do nothing special after    1  : show stdout    2  : show and select stdout    > 2 : no action at present (counts as equivalent to 0)    */#if VERSION2 == TRUE    if (!(gHawkIsRunning && gInBackground))        {        AnnounceCompletion();        }    if (gHawkIsRunning && gInBackground)        DoNotify();    else#endif    if (gacc.result == -2)        ShowResult(gacc.stdErrFileName);    else if (gacc.result == 1 || gacc.result == 2)        {        if (ShowResult(gacc.stdOutFileName) && gacc.result == 2)            SelectResult();        }#if VERSION2 == TRUE    gHawkIsRunning = FALSE;#endif    /* A small cleanup after */    if (gacc.thisCodeName)        DisposPtr(gacc.thisCodeName);    }#if VERSION2 == TRUEvoid XableDrag_ons(short menuID, Boolean enable)    {    MenuHandle menu = GetMHandle(menuID);    char    mText[64];    short        i;        if (!menu) return;    i = CountMItems(menu);    GetItem(menu, i, mText);    while (i >= 1 && mText[1] != '-')        {        if (enable)            EnableItem(menu, i);        else            DisableItem(menu, i);        --i;        GetItem(menu, i, mText);        }    }/* Post a notify. Beep, small icon, diamond beside calling app's name.NOTE when the calling app resumes, it should remove this notify andshow results, with        if (gNotifying)            {            NMRemove(&gNotifyRec);            if (gNotifyRec.nmIcon)                ReleaseResource(gNotifyRec.nmIcon);            gNotifying = FALSE;            ShowResultsAfterNotify();            }*/void DoNotify()    {    OSErr nmError;        if (!gInBackground) return;    gNotifyRec.qType = nmType;    gNotifyRec.nmMark = 1;    gNotifyRec.nmIcon = GetResource('SICN', 128); /* or NULL */    HNoPurge(gNotifyRec.nmIcon);    gNotifyRec.nmSound = (Handle)-1L;    gNotifyRec.nmStr = 0L;    gNotifyRec.nmResp = (NMProcPtr)0L;    gNotifyRec.nmRefCon = 0L;        nmError = NMInstall(&gNotifyRec);    gNotifying = TRUE;    }void ShowResultsAfterNotify()    {    if (gacc.result == -2)        ShowResult(gacc.stdErrFileName);    else if (gacc.result == 1 || gacc.result == 2)        {        if (ShowResult(gacc.stdOutFileName) && gacc.result == 2)            SelectResult();        }    FlushEvents(activMask+mDownMask+mUpMask, 0);    }void AnnounceCompletion()    {    long    startTime, endTime;            SysBeep(2);    Delay(0L, &startTime);    endTime = startTime;    while (endTime - startTime < 50L)        Delay(0L, &endTime);    FlushEvents(62, 0);    }#endif/* If you don't support some extensions, set the pointer for it to NULL here. */Boolean SetUpCodeCommunication(char *progName, char *commandLineP)    {    short    len;#if SUPPORT_LEVEL >= BASICTEXT    /* MyTextInFront(), which should return TRUE if one of your text    windows is in front or second from front (normally at the time of the call    the hAWK setup dialog will be the front window).    */    extern Boolean MyTextInFront(void);#if SUPPORT_LEVEL == CUSTOMSUPPORT    /* CanDoMultiFiles() should return TRUE if the user has selected    any files for multi-file operations, however you define that.    */    extern Boolean CanDoMultiFiles(void);#endif#endif    gacc.result = 0; /* clear before run - 0 means don't do anything after */    #if VERSION2 == TRUE    gacc.version = 2;#else    gacc.version = 1;#endif        gacc.extendID = 0; // Set to 'VER3' if you support PutAppClip    /* Extensions, set up every run */    gacc.GetScreenHeight_Ext = GetScreenHeight;    gacc.GetScreenWidth_Ext = GetScreenWidth;#if SUPPORT_LEVEL >= MINIMAL && SUPPORT_LEVEL <= BASICTEXT#if SUPPORT_LEVEL == BASICTEXT    if (MyTextInFront())        gacc.GetFrontText_Ext = GetFrontText; /* MODIFY GetFrontText()! */    else        gacc.GetFrontText_Ext = NULL;#else        gacc.GetFrontText_Ext = NULL;#endif    gacc.InDictionary_Ext = NULL;    gacc.GetNextMultiFile_Ext = NULL;    gacc.OKStopAlert_Ext = NULL;    gacc.MemoryAlert_Ext = NULL;    gacc.ShowWatchCursor_Ext = NULL;#if VERSION2 == TRUE    gacc.DoEventLoopOnce_Ext = DoEventLoopOnce;    gacc.GetAppClip_Ext = NULL;#else    gacc.DoEventLoopOnce_Ext = NULL;    gacc.GetAppClip_Ext = NULL;#endif#else /* CUSTOMSUPPORT - check all extension functions below. */    gacc.InDictionary_Ext = InDictionary;    if (MyTextInFront())        gacc.GetFrontText_Ext = GetFrontText;    else        gacc.GetFrontText_Ext = NULL;    if (CanDoMultiFiles())        gacc.GetNextMultiFile_Ext = GetNextMultiFile;    else        gacc.GetNextMultiFile_Ext = NULL;    gacc.OKStopAlert_Ext = OKStopAlert;    gacc.MemoryAlert_Ext = MemoryAlert;        gacc.ShowWatchCursor_Ext = ShowWatchCursor;#if VERSION2 == TRUE    gacc.DoEventLoopOnce_Ext = DoEventLoopOnce;    gacc.GetAppClip_Ext = GetAppClip;    gacc.extendID = 'VER3';#else    gacc.DoEventLoopOnce_Ext = NULL;    gacc.GetAppClip_Ext = NULL;#endif#endif        if (gacc.extendID == 'VER3')        gacc.PutAppClip_Ext = PutAppClip;    else        gacc.PutAppClip_Ext = NULL;        // Command line arg.    gacc.commandLine = commandLineP;    if (commandLineP != NULL)        {        gacc.extend2ID = 'VER4';        }    else        {        gacc.extend2ID = 0;        }    /* Set up code resource name for each call. */    len = progName[0];    gacc.thisCodeName = NewPtr(len+1);    if (MemError() != noErr)        return(FALSE); /* No big deal - but suggests code resource will                        run into trouble real quick if can't get 32 bytes                        now...*/    BlockMove(progName, gacc.thisCodeName, len);    gacc.thisCodeName[len] = '\0';    return(TRUE);    }/* This function is called by CallResource() to display the TEXT resultof a code resource run. If your application supports TEXT files, you willhave a function that takes a file name and vRefNum as arguments, and displaysthe TEXT file in a window - that's the one to use.A small but important complication: if the file is already being displayedin a window, your application should close it without asking to savechanges, and then reread it from disk. Changes not saved, because theseare temporary files needed for communication between the application andthe code resource. */Boolean ShowResult(char *name)    {#if SUPPORT_LEVEL >= RESULTSONLY    short vrefnum;    char filename[32];    short len = strlen(name);    Ptr    endPtr = name + len, startPtr = endPtr;    extern Boolean MyAppShowResult(short vRefNum, char *fileName);    while (startPtr >= name)        {        if (*startPtr == ':')            break;        --startPtr;        }    ++startPtr;    if (startPtr >= endPtr) return(FALSE);    filename[0] = endPtr - startPtr;    BlockMove(startPtr, filename+1, filename[0]);        vrefnum = OpenWorkingDirectoryFromFullName(name, (short)(startPtr - name));    if (!vrefnum) return(FALSE);    return(MyAppShowResult(vrefnum, filename));#else    return(FALSE);#endif/* For reference, the entire "MyAppShowResult" function for EnterAct is    if (wdPtr = IsFileOpen(fileName, vRefNum))        DoForcedCloseWindow(wdPtr);    return(DoOpenFile(text, FALSE, vRefNum, fileName));*/    }/* This function should select all of the text in the front window, afterchecking that the front window is indeed a text window. */void SelectResult()    {#if SUPPORT_LEVEL >= RESULTSONLY    extern void MyAppSelectResult(void);        MyAppSelectResult();#endif    }/* Pascal strings *//* Copy one pascal string to another */void CopyPStr(Byte *srcStr, Byte *dstStr)    {    long   srcLen = srcStr[0];    BlockMove(srcStr, dstStr, srcLen + 1);    }/* Append pascal s2 to pascal s1, avoiding overflow. */void AppendPStr(Byte *s1, Byte *s2)    {    short    s1Len = s1[0];    short    s2Len = s2[0];    if (s1Len + s2Len > 255)        s2Len = 255 - s1Len;    if (s2Len)        {        BlockMove (s2 + 1, s1 + s1Len + 1, s2Len);        s1Len += s2Len;        s1[0] = s1Len;        }    }Boolean PasEqualStrs(char *aStr, char *bStr)    {    short i, lena = aStr[0], lenb = bStr[0];        if (!lena || !lenb || lena != lenb)return(FALSE);    for (i = 1; i <= lena; ++i)        {        if (aStr[i] != bStr[i])            return(FALSE);        }    return(TRUE);    }/* Files, names and locations *//* NOTE the following two functions are based on examples suppliedby Apple on one of their DTS disks - error checking has been added,and these versions are independent of the signed vs unsigned charcontroversy surrounding str255. Byte is defined in MacTypes.hfor THINK C v4. *//* Warning, these calls can fail! And why not? Everything else can... *//* Bug, these two are not for use by unix imitations such as A/UX. *//* Construct "\pDisk:folder1:folder2:...folderN:" where folderNcontains the file of interest. */Byte *FullPathNameFromDirectory(long DirID, short vRefNum, Byte *s)    {    CInfoPBRec    pb;    Byte        directoryName[256];    s[0] = 0;    pb.dirInfo.ioNamePtr = (StringPtr)directoryName;    pb.dirInfo.ioDrParID = DirID;    do         {        pb.dirInfo.ioVRefNum = vRefNum;        pb.dirInfo.ioFDirIndex = -1;        pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID;        if (PBGetCatInfo(&pb, FALSE))            {            break;            }        /* Append a colon  */        AppendPStr(directoryName, (Byte *)"\p:");        AppendPStr(directoryName, s);        CopyPStr(directoryName, s);        } while (pb.dirInfo.ioDrDirID != 2);    return(s);    }Byte *FullPathNameFromVRefNum(short vRefNum, Byte *s)    {    WDPBRec    pb;    pb.ioNamePtr = NULL;    pb.ioVRefNum = vRefNum;    pb.ioWDIndex = 0;    pb.ioWDProcID = 0;    if (PBGetWDInfo(&pb,false))        {        s[0] = 0;        return(s);        }    return(FullPathNameFromDirectory(pb.ioWDDirID,pb.ioWDVRefNum,s));    }/* Determine working directory for file based on full path name. */short    OpenWorkingDirectoryFromFullName(char *name, short len)    {    WDPBRec        theParms;    OSErr     IOResult;    char volname[256];        volname[0] = len;    BlockMove(name, volname+1, len);        theParms.ioCompletion = NULL;    theParms.ioVRefNum = 0;    theParms.ioNamePtr = (StringPtr)volname;    theParms.ioWDDirID = 0;    theParms.ioWDProcID = 'ERIK';    if (IOResult = PBOpenWD(&theParms, FALSE)) /* IM IV pg 158 */        {        OKStopAlert("Disk may not be on-line, \or file may have been moved, deleted, or renamed.");        theParms.ioVRefNum = 0;        }    return(theParms.ioVRefNum);    }/* The extension functions.*//* InDictionary() returns the general C typeof a word, according to the following table:value    C type0        none - keyword, comment word, local variable, operator etc1        #define or macro name    eg    #define TAB '\t'2        variable name with more than function scope4        function or method name8        enum constant16        typedef name32        struct tag64        union tag128        enum tagSee hAWK cross-referencing programs for an example of usage. It's unlikelythat you will be able to provide an equivalent for this function, andthere’s no great loss if you don’t. */short InDictionary(char *tokenName)    {#if SUPPORT_LEVEL == CUSTOMSUPPORT    extern short InMyAppDictionary(char *s);        return(InMyAppDictionary(tokenName));#else    return(0);#endif    }/* This extension function should copy all or the selected part of thetext in the frontmost window to a Handle. If the front window is not atext window, you should try the second-front window - if it isn't texteither, return NULL. Front OR second front, because a dialog window may bethe front window at the time - this is the case with hAWK, for example.*/Handle GetFrontText(Boolean getItAll)    {#if SUPPORT_LEVEL >= BASICTEXT    extern Handle MyAppGetFrontText(Boolean getItAll);        return(MyAppGetFrontText(getItAll));#else    return(NULL);#endif    }/* This function should retrieve file names and vRefNums from a oneor two-dimensional list of files. If *panePtr == -1, you are being askedfor the first file, otherwise the next file. When there are no more files,set *indexPtr = -1. If you have a two-dimensional list, think of panePtr asthe column index and indexPtr as the row index. For a one-dimensional list,use indexPtr to keep track of where you are - just remember to set panePtr tosomething != -1 during the first call. Other than setting panePtr to somethingbesides -1 during the first call, and setting indexPtr to -1 when there areno more files, you can use them for tracking which file comes next in any wayyou want.If you perhaps use full path names, see OpenWorkingDirectoryFromFullName()above for hints on how to convert to filename/vRefNum.clearFlag TRUE means clear the file from your list; FALSE means leave it in thelist. Normally FALSE is best - someone might want to reuse the list quite soon,as in running two hAWK programs on the same list of files.*/void GetNextMultiFile(short *panePtr, short *indexPtr,             short *vRefNumPtr, char *fileName, Boolean clearFlag)    {#if SUPPORT_LEVEL == CUSTOMSUPPORT    extern void GetNextFileToSearch(short *panePtr, short *indexPtr,         short *vRefNumPtr, char *fileName, Boolean clearFlag);        GetNextFileToSearch(panePtr, indexPtr,                 vRefNumPtr, fileName, clearFlag);#else    *indexPtr = -1;#endif    }/* If you have an alert mechanism with just an OK button that accepts Cstrings, insert it here. Return of 1 means alert was shown and userclicked OK, return of 0 means the alert was not shown. If this happens,it would be quite OK for your alert function to try to get more memory orshow an out-of memory alert before returning the 0 or 1. */short OKStopAlert(Ptr cstringPtr)    {#if SUPPORT_LEVEL == CUSTOMSUPPORT/* Left in from EnterAct as an example - EnterAct uses FlexAlert(),essentially as published in MacTutor Jan '91. As a small refinement, itwill display an out-of-memory alert if it runs into trouble. FlexAlertsizes the alert box to fit the text, and also formats the text nicely. */    extern short FlexAlert(short buttonMode, short whichIcon, Ptr csPtr);#define JUSTOK    0#define STOPICON    0    return(FlexAlert(JUSTOK, STOPICON, cstringPtr));#else    return(0);#endif    }/* Advise the user that memory has run out during code resource execution.You must have something for this kicking around in your application - atext message is much more likeable than a beep if things fo worng. */void MemoryAlert()    {#if SUPPORT_LEVEL == CUSTOMSUPPORT    extern void DoMemoryAlert(short msgNum, long memLimit);#define NONELEFT        4    DoMemoryAlert(NONELEFT, 0L);#else    SysBeep(2);#endif    }short GetScreenHeight(void)    {    return(qd.screenBits.bounds.bottom - qd.screenBits.bounds.top);    }short GetScreenWidth()    {    return(qd.screenBits.bounds.right - qd.screenBits.bounds.left);    }void ShowWatchCursor()    {#if SUPPORT_LEVEL == CUSTOMSUPPORT    extern void MySetWatchCursor(void);        MySetWatchCursor();#endif    /* this goes something like:    CursHandle        Watch;    Watch = GetCursor(watchCursor); <- ToolboxUtil.h  enum constant --    if (Watch)        SetCursor (*Watch);    else        InitCursor();    */    }void DoEventLoopOnce()    {#if VERSION2 == TRUE    extern void HandleOneEvent(void);        HandleOneEvent();#endif    }Handle GetAppClip()    {#if SUPPORT_LEVEL == CUSTOMSUPPORT#if VERSION2 == TRUE    extern pascal Handle    PEGetScrap(void);    return(PEGetScrap());#endif#endif    return(NULL);    }short PutAppClip(char *newClipStr)    {    // Put the C string newClipStr on your application's private clip,    // as for example make a handle here, put the string in it, and    // set TextEdit's scrap to the new handle.    // return 0 if failure, 1 if success.    return 0;    }~~ñ]oPDrive' πÊCall_Resource.cTEXTKEENTEXTKEEN¶íAëòCancelàò≈àSave as:Δ1.Ä8⁄J EjectR⁄d Driveù≠¬≈Ä02pD∫
  2.     Monaco≠Às/$H    MonacoW¸$W¸$≠Àx)wvwxtè~~ñ?c ÃñETAB2EFNT>JAGZJWSIZVMPSRbMWBBnÏˇˇΡˇÌˇˇÓˇˇÌˇˇ*ˇˇv